package com.macro.mall.portal.service.activityImpl;

import com.alibaba.fastjson.JSON;
import com.github.pagehelper.PageHelper;
import com.macro.mall.common.api.CommonPage;
import com.macro.mall.common.api.CommonResult;
import com.macro.mall.common.service.RedisService;
import com.macro.mall.common.util.DateUtil;
import com.macro.mall.mapper.OmsOrderMapper;
import com.macro.mall.mapper.OmsOrderSettingMapper;
import com.macro.mall.mapper.PmsProductMapper;
import com.macro.mall.model.*;
import com.macro.mall.portal.component.MessageSender;
import com.macro.mall.portal.dao.PortalOrderDao;
import com.macro.mall.portal.domain.OrderParam;
import com.macro.mall.portal.domain.QueueEnum;
import com.macro.mall.portal.dto.PmsProductDto;
import com.macro.mall.portal.service.ActivityService;
import com.macro.mall.portal.service.OmsPortalOrderService;
import com.macro.mall.portal.service.UmsMemberService;
import com.quyum.mall.market.config.RedisKey;
import com.quyum.mall.market.entity.MarketSmsGroupBuy;
import com.quyum.mall.market.entity.MarketSmsRound;
import com.quyum.mall.market.entity.MarketSmsRoundProduct;
import com.quyum.mall.market.mapper.MarketSmsRoundMapper;
import com.quyum.mall.market.service.activity.impl.ActivityServiceImpl;
import com.quyum.mall.market.service.redis.StartActivityService;
import com.quyum.mall.market.service.stock.HandelStockService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class ActivityImpl extends ActivityServiceImpl implements ActivityService , StartActivityService, HandelStockService {
    @Autowired
    private RedisService redisService;
    @Autowired
    private UmsMemberService memberService;
    @Autowired
    private OmsPortalOrderService orderService;
    @Autowired
    private MessageSender messageSender;
    @Autowired
    private PmsProductMapper productMapper;
    @Autowired
    private PortalOrderDao portalOrderDao;
    @Autowired
    private OmsOrderSettingMapper orderSettingMapper;
    @Autowired
    private OmsOrderSettingMapper settingMapper;
    @Autowired
    private OmsOrderMapper orderMapper;
    @Autowired
    private MarketSmsRoundMapper roundMapper;

    @Override
    public void cancelGroupBuy(MarketSmsRound ro, MarketSmsGroupBuy groupBuy) {
        List<Long> getMin = new ArrayList<>();
        OmsOrderSetting orderSetting = orderSettingMapper.selectByPrimaryKey(1L);
        if(ro!=null){
            Long endTime = ro.getEndTime().getTime()-(System.currentTimeMillis());
            getMin.add(endTime);
        }
        if(groupBuy!=null){
            Long  groupBuyEndDate = groupBuy.getAddTime().getTime() + orderSetting.getGroupBuyOrderOvertime() * 60 * 1000-(System.currentTimeMillis());
            getMin.add(groupBuyEndDate);
        }
        if(!CollectionUtils.isEmpty(getMin)){
            Long aLong = getMin.stream().min(Comparator.comparing(e -> e)).get();
            assert groupBuy != null;
            this.messageSender.sendMessage(groupBuy.getId(),aLong,QueueEnum.QUEUE_TTL_GROUP_BUY_CANCEL);
        }
    }

    @Override
    public Boolean hasQualification(MarketSmsRound ro, MarketSmsRoundProduct skuStockProduct, Integer num, Long replaceUserId) {
        Boolean flag = true;
        Long id = null;
        if (replaceUserId != null) {
            id = replaceUserId;
        }else {
            UmsMember currentMember = this.memberService.getCurrentMember();
            id = currentMember.getId();
        }
        String key = new StringBuffer(RedisKey.MEMBER_HAS_KEY)
                .append(ro.getId()).append("_")
                .append(id).append("_")
                .append(skuStockProduct.getProductId()).append("_")
                .append(skuStockProduct.getSkuId()).toString();
        Object o = this.redisService.get(key);
        Integer hasBuyNum = 0;
        if(o!=null){
            if(!ro.getPurchaseLimit().equals(-1)){
                hasBuyNum = (Integer)o;
            }
        }
        if(!ro.getPurchaseLimit().equals(-1)&&(ro.getPurchaseLimit()-hasBuyNum)<num){
            flag = false;
        }
        return flag;
    }

    @Override
    public Long generateOrder(Map<String, Object> params) {
        OrderParam orderParam = JSON.parseObject(JSON.toJSONString(params),OrderParam.class);
        Map<String, Object> result =new HashMap<>();
        if(CollectionUtils.isEmpty(orderParam.getCartIds())){
            //商品详情页下单
            return this.orderService.generateOrderItemDetails(orderParam);
        }else{
            //购物车下单
            return this.orderService.generateOrder(orderParam);
        }
    }


    @Override
    public void hasBuyNum(MarketSmsRound ro,MarketSmsRoundProduct skuStockProduct, Integer num, Long replaceUserId) {
        Long id = null;
        if (replaceUserId != null) {
            id = replaceUserId;
        }else {
            UmsMember currentMember = this.memberService.getCurrentMember();
            id = currentMember.getId();
        }
        String key = new StringBuffer(RedisKey.MEMBER_HAS_KEY)
                .append(ro.getId()).append("_")
                .append(id).append("_")
                .append(skuStockProduct.getProductId()).append("_")
                .append(skuStockProduct.getSkuId()).toString();
        Object o = this.redisService.get(key);
        Integer hasBuyNum = 0;
        if(o!=null){
            hasBuyNum = (Integer)o;
        }
        hasBuyNum +=num;
        this.redisService.setMilliSeconds(key,hasBuyNum, DateUtil.getReduce(ro.getEndTime()));
    }


    @Override
    public void cancelOrder(Long orderId,Boolean cancelWaitGroupBuy) {
        this.orderService.cancelOrder(orderId,"",cancelWaitGroupBuy);

    }

    @Override
    public void cancelOrderTtl(MarketSmsRound ro, MarketSmsGroupBuy groupBuy, Long orderId) {
        OmsOrderSetting orderSetting = orderSettingMapper.selectByPrimaryKey(1L);
        OmsOrder omsOrder = this.orderMapper.selectByPrimaryKey(orderId);
        Long aLong = this.getaLong(ro, groupBuy, orderId,orderSetting,omsOrder) + omsOrder.getCreateTime().getTime()-System.currentTimeMillis();
        if(omsOrder.getOrderType().equals(0)||omsOrder.getOrderType().equals(1)){
            messageSender.sendMessage(orderId, aLong, QueueEnum.QUEUE_TTL_ORDER_CANCEL);
        }else if(omsOrder.getOrderType().equals(2)){
            messageSender.sendMessage(orderId, aLong, QueueEnum.QUEUE_TTL_SEC_KILL_CANCEL);
        }else if(omsOrder.getOrderType().equals(3)){
            System.out.println("取消团购订单");
            messageSender.sendMessage(orderId, aLong, QueueEnum.QUEUE_TTL_GROUP_BUY_ORDER_CANCEL);
        }

    }
    @Override
    public Long getaLong(MarketSmsRound ro, MarketSmsGroupBuy groupBuy, Long orderId,OmsOrderSetting orderSetting,OmsOrder omsOrder) {
        Long delayTimes = 0L;
        //获取订单超时时间
        List<Long> getMin = new ArrayList<>();

        //正常付款超时时间
        switch (omsOrder.getOrderType()){
            case 0:
                /**
                 * 普通商品
                 */
            case 1:
                /**
                 * 组合商品
                 */
            case 4:
                /**
                 * 换货商品
                 */
                delayTimes= (long) orderSetting.getNormalOrderOvertime() * 60 * 1000 + omsOrder.getCreateTime().getTime()-System.currentTimeMillis();
                break;
            case 2:
                /**
                 * 秒杀
                 */
                delayTimes= (long) orderSetting.getFlashOrderOvertime() * 60 * 1000+ omsOrder.getCreateTime().getTime()-System.currentTimeMillis();
                break;
            case 3:
                /**
                 * 团购商品
                 */
                delayTimes= (long) orderSetting.getGroupBuyOrderPayOvertime() * 60 * 1000 + omsOrder.getCreateTime().getTime()-System.currentTimeMillis();
                break;
            default:
                delayTimes= 0L;
                break;
        }
        if(!delayTimes.equals(0L)){
            getMin.add(delayTimes);
        }
        if(ro !=null){
            Long endTime = ro.getEndTime().getTime()-(System.currentTimeMillis());
            getMin.add(endTime);
        }
        if(groupBuy !=null){
            Long  groupBuyEndDate = omsOrder.getCreateTime().getTime() + orderSetting.getGroupBuyOrderOvertime() * 60 * 1000-System.currentTimeMillis();
            getMin.add(groupBuyEndDate);
        }
        Long aLong = 0L;
        if(!CollectionUtils.isEmpty(getMin)){
            aLong = getMin.stream().min(Comparator.comparing(e -> e)).get();
            //发送延迟消息
        }
        return aLong;
    }

    @Override
    public List<Map<String,String>> getPicList(List<Long> orderIds) {
        List<Map<String,String>> picList = this.portalOrderDao.getPicList(orderIds);
        return picList;

    }

    @Override
    public Date getGroupBuyEndTime(MarketSmsGroupBuy groupBuy) {
        MarketSmsRound smsRound = this.roundMapper.selectByPrimaryKey(groupBuy.getRoundId());
        Date endTime = groupBuy.getAddTime();
        OmsOrderSetting omsOrderSetting = this.orderSettingMapper.selectByPrimaryKey(1L);
        Integer groupBuyOrderOvertime = omsOrderSetting.getGroupBuyOrderOvertime();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(endTime);
        calendar.add(Calendar.MINUTE,groupBuyOrderOvertime);
        endTime = calendar.getTime();
        if(endTime.after(smsRound.getEndTime())){
            endTime = smsRound.getEndTime();
        }
        return endTime;
    }


    @Override
    public CommonResult<CommonPage<PmsProductDto>> getDetails(Integer pageSize, Integer pageNum, Long roundId) {
        Object o = this.redisService.get(RedisKey.ROUND_STARTING_KEY + roundId);
        if(o!=null){
            MarketSmsRound round = (MarketSmsRound) o;
            List keys1 = this.redisService.keys(RedisKey.ROUND_SKU_STOCK_KEY);
            List<MarketSmsRoundProduct> products = new ArrayList<>();
            if(!CollectionUtils.isEmpty(keys1)){
                for (Object obj:keys1) {
                    if(obj instanceof  MarketSmsRoundProduct){
                        MarketSmsRoundProduct product = (MarketSmsRoundProduct)obj;
                        if(product.getRoundId().equals(roundId)){
                            products.add(product);
                        }
                    }
                }
            }
            List<PmsProductDto> productDtos = new ArrayList<>();
            if(!CollectionUtils.isEmpty(products)){
                List<Long> productIds = products.stream().map(MarketSmsRoundProduct::getProductId).collect(Collectors.toList());
                Map<Long, List<MarketSmsRoundProduct>> roundProductMap = products.stream().collect(Collectors.groupingBy(MarketSmsRoundProduct::getProductId));
                PmsProductExample example = new PmsProductExample();
                example.createCriteria().andIdIn(productIds);
                PageHelper.startPage(pageNum, pageSize);
                List<PmsProduct> pmsProducts = this.productMapper.selectByExample(example);
                CommonPage<PmsProduct> productCommonPage = CommonPage.restPage(pmsProducts);
                List<PmsProduct> list = productCommonPage.getList();
                if(!CollectionUtils.isEmpty(list)){
                    for (PmsProduct e:list) {
                        PmsProductDto dto = new PmsProductDto();
                        BeanUtils.copyProperties(e,dto);
                        BigDecimal activityPrice =new BigDecimal("100000000000");
                        int activityTotalNum = 0;
                        int activityTotalResidueNum = 0;
                        Integer groupSize = 0;
                        List<MarketSmsRoundProduct> marketSmsRoundProducts;
                        if(!round.getStatus().equals(5)){
                            marketSmsRoundProducts= roundProductMap.get(e.getId());
                        }else{
                            marketSmsRoundProducts = new ArrayList<>();
                            List keys = this.redisService.keys(RedisKey.ROUND_SKU_STOCK_KEY + e.getId());
                            for (Object f:keys) {
                                MarketSmsRoundProduct marketSmsRoundProduct=  (MarketSmsRoundProduct)f;
                                if(marketSmsRoundProduct.getRoundId().equals(roundId)){
                                    marketSmsRoundProducts.add(marketSmsRoundProduct);
                                    groupSize = marketSmsRoundProduct.getGroupSize();
                                }
                            }
                        }
                        if(!CollectionUtils.isEmpty(pmsProducts)){
                            List<MarketSmsRoundProduct> activityList = marketSmsRoundProducts.stream().filter(f -> f.getActivityPrice() != null).collect(Collectors.toList());
                            for (MarketSmsRoundProduct g:activityList) {
                                if(activityPrice.compareTo(g.getActivityPrice())>0){
                                    activityPrice = g.getActivityPrice();
                                    groupSize = g.getGroupSize();
                                }
                            }
                            activityTotalNum = marketSmsRoundProducts.stream().filter(f -> f.getNum() != null).collect(Collectors.toList()).stream().mapToInt(MarketSmsRoundProduct::getNum).sum();
                            activityTotalResidueNum = marketSmsRoundProducts.stream().filter(f -> f.getResidueNum() != null).collect(Collectors.toList()).stream().mapToInt(MarketSmsRoundProduct::getResidueNum).sum();
                        }
                        dto.setRoundId(roundId);
                        dto.setActivityType(round.getType());
                        dto.setActivityPrice(activityPrice);
                        dto.setActivityTotalNum(activityTotalNum);
                        dto.setActivityTotalResidueNum(activityTotalResidueNum);
                        dto.setGroupSize(groupSize);
                        productDtos.add(dto);
                    }
                }
                CommonPage<PmsProductDto> result = new CommonPage<>();
                BeanUtils.copyProperties(productCommonPage,result);
                result.setList(productDtos);
                return CommonResult.success(result);
            }else{
                return CommonResult.failed("该活动场次没有对应的商品");
            }
        }else{
            MarketSmsRound marketSmsRound = roundMapper.selectByPrimaryKey(roundId);
            Integer status = marketSmsRound.getStatus();
            if (status.equals(MarketSmsRound.STATUS.WAIT_LOCK_STOCK.value)) {
                return CommonResult.failed("该活动场次暂未开始");
            }else if (status.equals(MarketSmsRound.STATUS.WAIT.value)) {
                return CommonResult.failed("该活动场次暂未开始");
            }else if (status.equals(MarketSmsRound.STATUS.FINISH.value)) {
                return CommonResult.failed("该活动场次已结束");
            }else {
                return CommonResult.failed("该活动场次已结束");
            }
        }
    }
    @Override
    public CommonResult<List<MarketSmsRound>> getListCommonResult(Integer type) {
        List<MarketSmsRound> result = new ArrayList<>();
        List keys = this.redisService.keys(RedisKey.ROUND_STARTING_KEY);
        List<MarketSmsRound> onList = new ArrayList<>();
        List<MarketSmsRound> afterList = new ArrayList<>();
        if(!CollectionUtils.isEmpty(keys)){
            for (Object o:keys) {
                MarketSmsRound marketSmsRound = (MarketSmsRound)o;
                if(marketSmsRound.getType().equals(type)){
                    marketSmsRound.setProducts(null);
                    onList.add(marketSmsRound);
                }
            }
        }
        List keys1 = this.redisService.keys(RedisKey.ROUND_KEY_BEFORE);
        Date start = DateUtil.getStartOfDay(new Date());
        Date end = DateUtil.getEndOfDay(new Date());
        if(!CollectionUtils.isEmpty(keys1)){
            for (Object o:keys1) {
                if(o!=null&&(o instanceof MarketSmsRound)){
                    MarketSmsRound marketSmsRound = (MarketSmsRound)o;
                    if(marketSmsRound.getType().equals(type)){
                        if(start.before(marketSmsRound.getStartTime())
                                &&end.after(marketSmsRound.getStartTime())
                                &&marketSmsRound.getStatus().equals(MarketSmsRound.STATUS.WAIT.value)){
                            //获取当天的秒杀场次
                            marketSmsRound.setProducts(null);
                            afterList.add(marketSmsRound);
                        }
                    }
                }
            }
        }
        afterList.sort(new Comparator<MarketSmsRound>() {
            @Override
            public int compare(MarketSmsRound o1, MarketSmsRound o2) {
                long time = o1.getStartTime().getTime();
                long time1 = o2.getStartTime().getTime();
                return Long.compare(time, time1);
            }
        });
        result.addAll(onList);
        result.addAll(afterList);
        return CommonResult.success(result);
    }

    @Override
    public void start(String key) {
        return;
    }

    @Override
    public String lockStock(Long roundId) {
        return null;
    }

    @Override
    public void releaseActivityStock(MarketSmsRoundProduct roundProduct, Long skuId) {

    }
    @Override
    public Boolean checkStock(MarketSmsRoundProduct product) {
        return null;
    }
}
